package com.wwdablu.soumya.lottiebottomnav;

import com.airbnb.lottie.value.LottieAnimationViewData;
import com.wwdablu.soumya.lottiebottomnav.util.AttrUtil;
import ohos.agp.animation.Animator;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.List;

/**
 * LottieBottomNav
 *
 * @since 2021-05-19
 */
public class LottieBottomNav extends DirectionalLayout {
    private List<MenuItem> menuItemList;
    private ArrayList<LottieViewCreator> lottieViews;
    private ILottieBottomNavCallback callback;
    private Config config;
    private Context mContext;
    private int selectedIndex;

    /**
     * LottieBottomNav
     *
     * @param context
     * @param attrs
     */
    public LottieBottomNav(Context context, AttrSet attrs) {
        super(context, attrs);
        this.mContext = context;
        setOrientation(HORIZONTAL);
        setAlignment(LayoutAlignment.CENTER);
        selectedIndex = 0;
        callback = new LottieBottomNavCallbackImpl();
        extractProperties(attrs);
    }

    /**
     * Assign the menu items that are to be displayed
     *
     * @param menuItemList List of menu items
     */
    public void setMenuItemList(List<MenuItem> menuItemList) {
        this.menuItemList = menuItemList;
        lottieViews = new ArrayList<>(menuItemList.size());
        prepareMenuItems();
    }

    /**
     * updateMenuItemFor
     *
     * @param index
     * @param menuItem
     */
    public void updateMenuItemFor(int index, MenuItem menuItem) {
        if (menuItemList == null || index < 0 || index > menuItemList.size()) {
            return;
        }

        lottieViews.get(index).lmiMenuItem.setSpeed(0f);
        menuItemList.set(index, menuItem);

        LottieViewCreator lottieViewCreator = new LottieViewCreator(mContext);
        lottieViewCreator.from(this, menuItem, selectedIndex == index, config);
        lottieViews.set(index, lottieViewCreator);

        removeComponentAt(index);
        ComponentContainer.LayoutConfig params = lottieViewCreator.menuContainer.getLayoutConfig();
        params.width = (getWidth() / menuItemList.size());
        lottieViewCreator.menuContainer.setLayoutConfig(params);
        lottieViewCreator.setTag(index);
        lottieViewCreator.setClickedListener(view -> {
            switchSelectedMenu((int) view.getTag());
        });
        lottieViewCreator.lmiMenuItem.addAnimatorListener(animatorListener);
        if (!config.isShowTextOnUnselected()) {
            lottieViewCreator.lmiMenuText.setVisibility(isSelected(index) ? VISIBLE : INVISIBLE);
        }
        addComponent(lottieViewCreator, index);
        lottieViewCreator.lmiMenuItem.setProgress(0F);

        LottieAnimationViewData select = new LottieAnimationViewData();
        select.setFilename(menuItem.selectedLottieName);
        select.repeatCount = menuItem.loop ? Integer.MAX_VALUE : 0;
        lottieViewCreator.lmiMenuItem.setAnimationData(select);

        lottieViewCreator.lmiMenuItem.playAnimation();
        lottieViewCreator.lmiMenuItem.setSpeed(1f);
    }

    /**
     * Set the index of the to be displayed as selected
     *
     * @param index Index
     */
    public void setSelectedIndex(int index) {
        if (lottieViews == null || lottieViews.size() == 0 || selectedIndex == index) {
            return;
        }

        // Boundary checks
        if (index < 0) index = 0;
        else if (index >= lottieViews.size()) index = lottieViews.size() - 1;

        switchSelectedMenu(index);
    }

    /**
     * Returns the currently selected menu index
     *
     * @return Index
     */
    public int getSelectedIndex() {
        return selectedIndex;
    }

    /**
     * Returns the menu item associated with the index
     *
     * @param index Index
     * @return MenuItem
     */
    public MenuItem getMenuItemFor(int index) {
        if (menuItemList == null || index < 0 || index > menuItemList.size()) {
            return null;
        }

        return menuItemList.get(index);
    }

    /**
     * Sets the callback to listen for the menu changes
     *
     * @param callback Callback
     */
    public void setCallback(ILottieBottomNavCallback callback) {
        this.callback = callback == null ? new LottieBottomNavCallbackImpl() : callback;
    }

    /**
     * setOrientation
     *
     * @param orientation
     */
    @Override
    public void setOrientation(int orientation) {
        super.setOrientation(HORIZONTAL);
    }

    /**
     * setAlignment
     *
     * @param alignment
     */
    @Override
    public void setAlignment(int alignment) {
        super.setAlignment(LayoutAlignment.CENTER);
    }

    /**
     * prepareMenuItems
     */
    private void prepareMenuItems() {
        int index = 0;
        lottieViews.clear();

        for (MenuItem menuItem : menuItemList) {
            LottieViewCreator lottieViewCreator = new LottieViewCreator(mContext);
            lottieViewCreator.from(this, menuItem, selectedIndex == index, config);

            lottieViewCreator.setTag(index);
            lottieViewCreator.setClickedListener(view -> switchSelectedMenu((int) view.getTag()));

            // lottieViewCreator.lmiMenuItem.addAnimatorListener(animatorListener);
            if (index == selectedIndex) {
                lottieViewCreator.lmiMenuItem.setProgress(0F);
                lottieViewCreator.lmiMenuItem.playAnimation();
                if (!config.isShowTextOnUnselected()) {
                    lottieViewCreator.lmiMenuText.setVisibility(Component.VERTICAL);
                }
            }else{
                if (!config.isShowTextOnUnselected()) {
                    lottieViewCreator.lmiMenuText.setVisibility(Component.INVISIBLE);
                }
            }

            lottieViews.add(lottieViewCreator);
            index++;
        }

        if (getWidth() == 0) {
            this.setLayoutRefreshedListener(new LayoutRefreshedListener() {
                @Override
                public void onRefreshed(Component component) {
                    setLayoutRefreshedListener(null);
                    updateUI();
                }
            });
        } else {
            updateUI();
        }
    }

    /**
     * 点击回调 newIndex
     *
     * @param newIndex
     */
    private void switchSelectedMenu(int newIndex) {

        if (newIndex == selectedIndex) {
            return;
        }

        //Pause any existing, or else it might impact
        lottieViews.get(selectedIndex).lmiMenuItem.pauseAnimation();
        lottieViews.get(selectedIndex).lmiMenuItem.setSpeed(0f);

        LottieViewCreator binding = lottieViews.get(newIndex);
        MenuItem menuItem = menuItemList.get(newIndex);


        LottieAnimationViewData select = new LottieAnimationViewData();
        select.setFilename(menuItem.selectedLottieName);
        select.repeatCount = menuItem.loop ? Integer.MAX_VALUE : 0;
        binding.lmiMenuItem.setAnimationData(select);
        binding.lmiMenuText.setTextColor(new Color(menuItem.fontItem.getTextSelectedColor()));
        binding.lmiMenuText.setTextSize(menuItem.fontItem.getSelectedTextSize(), Text.TextSizeType.FP);

        binding.lmiMenuItem.setSpeed(1f);
//        binding.lmiMenuItem.playAnimation();

        ComponentContainer.LayoutConfig params = binding.lmiMenuItem.getLayoutConfig();
        params.width = config.getSelectedMenuWidth();
        params.height = config.getSelectedMenuHeight();
        binding.lmiMenuItem.setLayoutConfig(params);

        binding.lmiMenuText.setVisibility(VISIBLE);

        callback.onMenuSelected(selectedIndex, newIndex, menuItem);

        //Set the unselected menu item properties

        binding = lottieViews.get(selectedIndex);
        menuItem = menuItemList.get(selectedIndex);

//        LottieAnimationViewData unSelect = new LottieAnimationViewData();
//        unSelect.setFilename(menuItem.unselectedLottieName);
//        unSelect.repeatCount = menuItem.loop ? Integer.MAX_VALUE : 0;
//        binding.lmiMenuItem.setAnimationData(unSelect);

        binding.lmiMenuItem.setAnimation(menuItem.unselectedLottieName);
        binding.lmiMenuText.setTextColor(new Color(menuItem.fontItem.getTextUnselectedColor()));
        binding.lmiMenuText.setTextSize(menuItem.fontItem.getUnselectedTextSize(), Text.TextSizeType.FP);

        binding.lmiMenuItem.setSpeed(0f);
//        binding.lmiMenuItem.pauseAnimation();
        binding.lmiMenuItem.setProgress(menuItem.lottieProgress);

        params = binding.lmiMenuItem.getLayoutConfig();
        params.width = config.getUnselectedMenuWidth();
        params.height = config.getUnselectedMenuHeight();
        binding.lmiMenuItem.setLayoutConfig(params);

        if (!config.isShowTextOnUnselected()) {
            binding.lmiMenuText.setVisibility(HIDE);
        }

        selectedIndex = newIndex;
    }

    private void updateUI() {
        removeAllComponents();
        int menuItemWidth = getWidth() / menuItemList.size();

        for (LottieViewCreator binding : lottieViews) {
            LottieViewCreator view = binding;
            ComponentContainer.LayoutConfig params = binding.menuContainer.getLayoutConfig();
            params.width = menuItemWidth;
            binding.menuContainer.setLayoutConfig(params);
            addComponent(view);
        }

        invalidate();
    }

    private void extractProperties(AttrSet attributeSet) {
        config = new Config(getContext());
        if (attributeSet == null) {
            return;
        }
        config.setSelectedMenuWidth(AttrUtil.getDimension(attributeSet, "menu_selected_width", -1));
        config.setSelectedMenuHeight(AttrUtil.getDimension(attributeSet, "menu_selected_height", -1));
        config.setUnselectedMenuWidth(AttrUtil.getDimension(attributeSet, "menu_unselected_width", -1));
        config.setUnselectedMenuHeight(AttrUtil.getDimension(attributeSet, "menu_unselected_height", -1));
        config.setShowTextOnUnselected(AttrUtil.getBooleanValue(attributeSet, "menu_text_show_on_unselected", true));
    }

    private boolean isSelected(int index) {
        return selectedIndex == index;
    }

    Animator.StateChangedListener animatorListener = new Animator.StateChangedListener() {
        @Override
        public void onStart(Animator animator) {
            callback.onAnimationStart(selectedIndex, menuItemList.get(selectedIndex));
        }

        @Override
        public void onStop(Animator animator) {
        }

        @Override
        public void onCancel(Animator animator) {
            callback.onAnimationCancel(selectedIndex, menuItemList.get(selectedIndex));
        }

        @Override
        public void onEnd(Animator animator) {
            callback.onAnimationEnd(selectedIndex, menuItemList.get(selectedIndex));
        }

        @Override
        public void onPause(Animator animator) {
        }

        @Override
        public void onResume(Animator animator) {
        }
    };
}
